/**
 * @Author:       lee
 * @DateTime:     2017-11-08 21:05:01
 * @Description:  类
 */
/**
 *  ES5实现类
 */
function Person(name) {
  this.name = name;
}

Person.prototype.sayName = function() {
  console.log(this.name)
}

var p1 = new Person('funlee')
p1.sayName()

console.log(p1 instanceof Person) // true
console.log(p1 instanceof Object) // true
  //-------------------------------------------------
  /**
   *  类的声明
   *  在构造函数中创建所有的私有属性
   */
class Person {
  //等同于Person构造函数
  constructor(name) {
      this.name = name
    }
    //等价于Person.prototype.sayName
  sayName() {
    console.log(this.name)
  }
}
console.log(Person.name) //和书上说的不一样呢
let p1 = new Person('funlee')
p1.sayName()

console.log(p1 instanceof Person)
console.log(p1 instanceof Object)

console.log(typeof Person)
console.log(typeof Person.prototype.sayName)
  //-------------------------------------------------
  /**
   *  类的表达式语法
   */
let Person = class {
  constructor(name) {
    this.name = name
  }
  sayName() {
    console.log(this.name)
  }
}
console.log(Person.name) //Person
let p1 = new Person('funlee')
p1.sayName()
  //-------------------------------------------------
  /**
   *  命名表达式
   */
let Person = class PersonClass {
  constructor(name) {
    this.name = name
  }
  sayName() {
    console.log(this.name)
  }
}
console.log(Person.name) // PersonClass

console.log(typeof Person) // function
console.log(typeof PersonClass) // undefined

let p1 = new Person('funlee')
p1.sayName()
  // PersonClass  有卵用？？
  //-------------------------------------------------
  /**
   *  将类作为函数的参数
   */
function createObj(classDef) {
  return new classDef()
}
let obj = createObj(class {
  say() {
    console.log('hello!!')
  }
})
obj.say()
  //-------------------------------------------------
  /**
   *  通过立即调用类构造函数，创建单例
   */
let person = new class {
  constructor(name) {
    this.name = name
  }
  sayName() {
    console.log(this.name)
  }
}('funlee')
person.sayName()
  //-------------------------------------------------
  /**
   *  访问器属性
   */


//-------------------------------------------------
/**
 *  可计算成员名称
 */
let methodName = 'sayName'
class PersonClass {
  constructor(name) {
      this.name = name
    }
    [methodName]() {
      console.log(this.name)
    }
}
//-------------------------------------------------
/**
 *  生成器方法
 */
class myClass { *
  createIterator() {
    yield 1;
    yield 2;
    yield 3;
  }
}
let instance = new myClass()
let iterator = instance.createIterator()

iterator.next()
iterator.next()
iterator.next()

//-------------------------------------------------
/**
 *  给类添加默认迭代器
 */
class Collection {
  constructor() {
      this.items = [];
    } *
    [Symbol.iterator]() {
      yield* this.items.values(); // 有错误
    }
}
var collection = new Collection()
collection.items.push(1)
collection.items.push(2)
collection.items.push(3)
collection.items.push(4)

for (let x of collection) {
  console.log(x);
}
//-------------------------------------------------
/**
 *  静态成员----ES5版本
 *  将方法添加到构造函数中来模拟静态成员
 */
function Person(name) {
  this.name = name
}
// 静态方法
Person.create = function(name) {
    return new Person(name)
  }
  // 实例方法
Person.prototype.sayName = function() {
  console.log(this.name)
}
var p1 = Person.create('funlee')
  //-------------------------------------------------
  /**
   *  静态成员----ES6版本
   *  将方法添加到构造函数中来模拟静态成员
   *  tip:
   *  不可在实例中访问静态成员，必须要直接在类中访问静态成员
   */
class Person {
  constructor(name) {
    this.name = name
  }
  sayName() {
    console.log(this.name)
  }
  static create(name) {
    return new Person(name)
  }
  static test() {
    console.log('静态方法--test')
  }
}
let p1 = Person.create('funlee')
p1.test() // p1.test is not a function
  //-------------------------------------------------
  /**
   *  ES5继承
   */
function Rectangle(length, width) {
  this.length = length;
  this, width = width;
}
Rectangle.prototype.getArea = function() {
  return this.length * this.width;
}

function Square(length) {
  Rectangle.call(this, length, length)
}

Square.prototype = Object.create(Rectangle.prototype, {
  constructor: {
    value: Square,
    enumerable: true,
    writable: true,
    configurable: true
  }
})

var square = new Square(3);

console.log(square.getArea())
console.log(square instanceof Square)
console.log(square instanceof Rectangle)
  //-------------------------------------------------
  /**
   *  ES6 类-继承
   *  继承自其他类的类称作派生类，如果在派生类中指定了构造函数则必须要调用super()
   */
class Rectangle {
  constructor(length, width) {
    this.length = length;
    this.width = width;
  }
  getArea() {
    return this.length * this.width
  }
}

class Square extends Rectangle {
  constructor(length) {
    //等价于Rectangle.call(this,length,length)
    super(length, length)
  }
}

var square = new Square(3);
console.log(square.getArea()) // 9
console.log(square instanceof Square) // true
console.log(square instanceof Rectangle) // true
  //-------------------------------------------------
  /**
   *  类方法遮蔽
   */

//-------------------------------------------------
/**
 * 
 */
class Point {
  constructor(value, name) {
    this.value = value
    this.name = name
    return Object.create(null)
  }
}
Object.assign(Point.prototype, {
  sayName() {
    console.log(this.name)
  },
  sayValue() {
    console.log(this.value)
  }
})
let test = new Point('value1111', 'name222222')
test.sayName()
test.sayValue()

for (item in test) {
  console.log(item)
}
/**
 * this指向
 */
class Person {
  say() {
    this.todos('hello')
  }
  todos(text) {
    console.log(text + 'world')
  }
}

const p1 = new Person()
p1.say()